﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using XamlMvp.Controls;

namespace XamlMvp
{
    public class PresenterBinder : IPresenterBinder
    {
        readonly IDictionary<Type, Delegate> presenters;

        public IPresenterContext Context { get; set; }       

        public PresenterBinder()
        {
            this.presenters = new Dictionary<Type, Delegate>();
        }

        public void RegisterPage<TView, TPresenter>(Func<TView, IDictionary<string, object>, PagePresenter<TView>> action) where TView : IViewPage
        {
            presenters.Add(typeof(TPresenter), action);
        }               

        public void RegisterControl<TView, TPresenter>(Func<TView, Presenter<TView>> action) where TView : IView
        {
            presenters.Add(typeof(TPresenter), action);            
        }
       
        public void Bind(UIElement view, IDictionary<string, object> state)
        {
            Type presenterType;
            if (TryGetPresenter(view, out presenterType))
            {
                InvokePresenter(presenterType, view, state);
            }
        }

        public void Bind(UIElement view)
        {
            Type presenterType;
            if (TryGetPresenter(view, out presenterType))
            {
                InvokePresenter(presenterType, view);
            }
        }

        bool TryGetPresenter(UIElement view, out Type type)
        {
            var presenterType = View.GetPresenter(view);

            if (presenterType == null)
            {
                type = null;
                return false;
            }
            
            type = presenterType.RuntimeType;

            return presenterType.IsBound;

        }
       
        void InvokePresenter(Type presenterType, params object[] args)
        {
            presenters[presenterType].DynamicInvoke(args);
        }

        public Type Find(string typeString)
        {
            return presenters.Keys.SingleOrDefault(t => t.FullName == typeString);
        }
    }
}
